package controllers

import (
    "gouniapp/configs"
	"net/http"
	"github.com/gin-gonic/gin"
	"github.com/patrickmn/go-cache"
	"errors"
	"log"
	"math/rand"
	"gorm.io/gorm"
	"fmt"
	"strconv"
	"strings"
	"time"
)

// 获取我的填报记录
func GetmyList(c *gin.Context) {
    type ListRequest struct {
	    Fl   int `json:"fl"`
    }
	var req ListRequest
	if err := c.ShouldBindJSON(&req); err != nil {
	    log.Printf("参数绑定错误: %v", err)
		JsonResponse(c, http.StatusBadRequest, "参数错误", err)
		return
	}
    currentUser := GetCurrentUser(c)
    if currentUser == nil {
        JsonResponse(c, http.StatusUnauthorized, "请重新登录", nil)
        return
    }
    // 获取所有表单配置
    var formSchemas []*configs.FormSchema
    cx := configs.DB.Select("ID", "FormName", "TableName", "Fields", "IsReservation")
    if req.Fl == 1 {
        cx.Where("is_reservation = ?", true)
    } else {
        cx.Where("is_reservation = ?", false)
    }
    if err := cx.Find(&formSchemas).Error; err != nil {
        JsonResponse(c, http.StatusInternalServerError, "获取表单配置失败", nil)
        return
    }
    // 收集所有表单数据
    responseData := make([]gin.H, 0)
    for _, form := range formSchemas {
        // 动态查询每个表的数据
        var results []map[string]interface{}
        tableName := form.TableName
        err := configs.DB.Table(tableName).Where("cjz = ?", currentUser.ID).Find(&results).Error
        if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
            log.Printf("查询表 %s 失败: %v", tableName, err)
            continue
        }
        // 只添加有数据的表单
        if len(results) > 0 {
            responseData = append(responseData, gin.H{
                "id":           form.ID,
                "form_name":    form.FormName,
                "table_name":   form.TableName,
                "is_reservation": form.IsReservation,
                "fields":       form.Fields,
                "data":         results,
            })
        }
    }
    JsonResponse(c, http.StatusOK, "获取成功", responseData)
}

// 判断是否是同一天
func isSameDay(t *time.Time, compareTime time.Time) bool {
	if t == nil {
		return false
	}
	compareTime = compareTime.Local()
	return t.Year() == compareTime.Year() && t.Month() == compareTime.Month() && t.Day() == compareTime.Day()
}

// 签到获得积分
func AddPoints(c *gin.Context) {
	currentUser := GetCurrentUser(c)
	if currentUser == nil {
		JsonResponse(c, http.StatusUnauthorized, "请重新登录", nil)
		return
	}
	var err error
	// 使用事务保证数据一致性
    err = configs.DB.Transaction(func(tx *gorm.DB) error {
        var user configs.User
        if err := tx.First(&user, currentUser.ID).Error; err != nil {
            return err
        }
        now := time.Now().Local()  // 新增本地时区转换
        if isSameDay(user.LastCheckIn, now) {
            return errors.New("今日已签到")
        }
        // 指针类型赋值（注意取地址操作）
        user.Points += 1
        user.LastCheckIn = &now  // 新增取地址操作
        if err := tx.Save(&user).Error; err != nil {
            return err
        }
        return configs.CreateMessage(tx, currentUser.ID, "签到成功", fmt.Sprintf("获得%d积分，当前总积分：%d", 1, currentUser.Points+1))
    })
	if err != nil {
		if err.Error() == "今日已签到" {
			JsonResponse(c, http.StatusBadRequest, err.Error(), nil)
		} else {
			JsonResponse(c, http.StatusInternalServerError, "系统错误", nil)
		}
		return
	}
    userCacheKey := fmt.Sprintf("user:%d", currentUser.ID)  //删除缓存
    configs.CRdb.Delete(userCacheKey)
	JsonResponse(c, http.StatusOK, "签到成功", gin.H{
		"points_added": 1,
		"total_points": currentUser.Points + 1,
	})
}

//微信登录
func Wxlogin(c *gin.Context) {
    code := c.Param("code")
	session, err := configs.MiniProgramApp.Auth.Session(c.Request.Context(), code)
	if err != nil || session.OpenID == "" {
		JsonResponse(c, http.StatusBadRequest, "微信登录失败", nil)
		return
	}
	openID := session.OpenID
	// 查询用户是否存在
	var user configs.User
	if err := configs.DB.Where("open_id = ?", openID).First(&user).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			// 返回openid给前端用于绑定
			JsonResponse(c, http.StatusOK, "需要绑定账号", gin.H{
				"token":    "need_bind",
				"openid":   openID,
			})
			return
		}
		JsonResponse(c, http.StatusInternalServerError, "系统错误", nil)
		return
	}
	// 生成包含更多信息的Token
	token, err := GenerateToken(&user)
	if err != nil {
		JsonResponse(c, http.StatusInternalServerError, err.Error(), nil)
		return
	}
    go func() {
        configs.CreateMessage(nil, user.ID, "微信登录成功", fmt.Sprintf("微信快捷登录操作，时间：%s", time.Now().Format("2006-01-02 15:04")))
    }()
	JsonResponse(c, http.StatusOK, "登录成功", gin.H{
		"token": token,
		"user": gin.H{
			"id":       user.ID,
			"username": user.Username,
			"role":     user.Role,
			"openid":   openID,
			"points":   user.Points,
			"last_check_in": user.LastCheckIn,
		},
	})
}

type BindRequest struct {
	OpenID   string `json:"openid" binding:"required"`
	Username string `json:"username" binding:"required"`
	Password string `json:"password" binding:"required"`
}

// 绑定openid
func BindAccount(c *gin.Context) {
	var req BindRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		JsonResponse(c, http.StatusBadRequest, "参数错误", nil)
		return
	}
	// 验证账号密码
	var user configs.User
	if err := configs.DB.Where("username = ?", req.Username).First(&user).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			JsonResponse(c, http.StatusNotFound, "用户不存在", nil)
			return
		}
		JsonResponse(c, http.StatusInternalServerError, "系统错误", nil)
		return
	}
	// 密码验证
	if !configs.CheckPasswordHash(req.Password, user.Password) {
		JsonResponse(c, http.StatusUnauthorized, "密码错误", nil)
		return
	}
	// 检查OpenID是否已被绑定
	var existingUser configs.User
	if err := configs.DB.Where("open_id = ?", req.OpenID).First(&existingUser).Error; err == nil {
		JsonResponse(c, http.StatusBadRequest, "该微信已绑定其他账号", nil)
		return
	}
	// 更新OpenID
	if err := configs.DB.Model(&user).Update("open_id", req.OpenID).Error; err != nil {
		JsonResponse(c, http.StatusInternalServerError, "绑定失败", nil)
		return
	}
	// 生成新Token
	token, err := GenerateToken(&user)
	if err != nil {
		JsonResponse(c, http.StatusInternalServerError, err.Error(), nil)
		return
	}
    userCacheKey := fmt.Sprintf("user:%d", user.ID) //删除缓存
    configs.CRdb.Delete(userCacheKey)
    go func() {
        configs.CreateMessage(nil, user.ID, "微信绑定通知", "您的账户已成功绑定微信，可使用微信快速登录。")
    }()
	JsonResponse(c, http.StatusOK, "绑定成功", gin.H{
		"token": token,
		"user": gin.H{
			"id":       user.ID,
			"username": user.Username,
			"role":     user.Role,
			"openid":   req.OpenID,
			"points":   user.Points,
			"last_check_in": user.LastCheckIn,
		},
	})
}

//获取用户个人信息
func GetUserInfo(c *gin.Context) {
    userObj, exists := c.Get("user")
    if !exists {
        JsonResponse(c, http.StatusUnauthorized, "需要登录", nil)
        return
    }
    operator, ok := userObj.(*configs.User)
    if !ok {
        JsonResponse(c, http.StatusUnauthorized, "用户信息异常", nil)
        return
    }
    // 生成缓存键
    userCacheKey := fmt.Sprintf("user:%d", operator.ID)
    // 尝试从缓存获取
    if cachedData, found := configs.CRdb.Get(userCacheKey); found {
        JsonResponse(c, http.StatusOK, "获取成功", cachedData)
        return
    }
    // 缓存未命中，查询数据库
    var existingUser configs.User
    if err := configs.DB.Select("id", "username", "name", "phone", "email", "role", "points", "last_check_in").
        Where("id = ?", operator.ID).First(&existingUser).Error; err != nil {
        JsonResponse(c, http.StatusNotFound, "用户不存在", nil)
        return
    }
    // 设置缓存（带随机过期时间防止雪崩）
    expiration := 5*time.Minute + time.Duration(rand.Intn(61))*time.Second
    configs.CRdb.Set(userCacheKey, existingUser, expiration)
    JsonResponse(c, http.StatusOK, "获取成功", existingUser)
}

// 定义接收结构体（处理可能的NULL值）
type UserSimpleInfo struct {
    ID   uint    `json:"id"`
    Name *string `json:"name"` // 使用指针处理NULL
    Role string  `json:"role"`
}
// 获取全部用户id=>name列表
func GetFormUsers(c *gin.Context) {
    var list []UserSimpleInfo
    // 添加角色过滤条件
    err := configs.DB.Model(&configs.User{}).Select("id", "name", "role").Find(&list).Error
    // 更精确的错误处理
    if err != nil {
        log.Printf("数据库查询失败: %v", err)
        JsonResponse(c, http.StatusInternalServerError, "服务暂时不可用", nil)
        return
    }
    // 处理空数据情况
    if len(list) == 0 {
        JsonResponse(c, http.StatusOK, "暂无项目管理员和填报员", nil)
        return
    }
    JsonResponse(c, http.StatusOK, "Success", list)
}

// 用户列表响应结构体
type UserListResponse struct {
    Items []configs.User `json:"items"` // 改为直接使用User结构体
    Total int64  `json:"total"`
}

// 分页获取用户列表
func GetUserlist(c *gin.Context) {
    // 参数绑定与校验
    var query configs.FormQuery
    if err := c.ShouldBindJSON(&query); err != nil {
        JsonResponse(c, http.StatusBadRequest, "请求参数错误", nil)
        return
    }
    // 限制最大每页数量
    if query.PageSize > 100 {
        query.PageSize = 100
    }
    // 初始化查询
    dbQuery := configs.DB.Model(&configs.User{}).Order("id DESC")
    // 搜索条件
    if query.Search != "" {
        search := "%" + query.Search + "%"
        dbQuery.Where("Username LIKE ? OR Name LIKE ?", search, search)
    }
    fmt.Println("搜索", query.Search)
    // 先查询总数（不带分页）
    var total int64
    if err := dbQuery.Count(&total).Error; err != nil {
        JsonResponse(c, http.StatusInternalServerError, "查询总数失败", nil)
        return
    }
    // 分页查询数据
    var users []configs.User
    err := dbQuery.Scopes(configs.Paginate(query.Page, query.PageSize)).
        Select("id, username, name, phone, email, role, points, last_check_in, open_id, created_at, updated_at"). // 排除敏感字段
        Find(&users).Error
    if err != nil {
        JsonResponse(c, http.StatusInternalServerError, "查询数据失败", nil)
        return
    }
    JsonResponse(c, http.StatusOK, "Success", UserListResponse{
        Items: users,
        Total: total,
    })
}

// 批量导入用户
func ImportUser(c *gin.Context) {
    currentUser := GetCurrentUser(c)
    if currentUser == nil {
        JsonResponse(c, http.StatusUnauthorized, "请先登录", nil)
        return
    }
	var users []configs.User
	if err := c.ShouldBindJSON(&users); err != nil {
		JsonResponse(c, http.StatusBadRequest, "请求数据格式错误", nil)
		return
	}
	if len(users) == 0 {
		JsonResponse(c, http.StatusBadRequest, "导入数据不能为空", nil)
		return
	}
	// 开启事务
	tx := configs.DB.Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()
	// 收集用户名并检查重复
	usernameMap := make(map[string]bool)
	duplicates := make([]string, 0)
	allUsernames := make([]string, len(users))
	for i, user := range users {
		allUsernames[i] = user.Username
		if usernameMap[user.Username] {
			duplicates = append(duplicates, user.Username)
		} else {
			usernameMap[user.Username] = true
		}
	}
	if len(duplicates) > 0 {
		tx.Rollback()
		JsonResponse(c, http.StatusConflict, "导入列表中存在重复用户名", gin.H{"duplicate_usernames": duplicates,})
		return
	}
	// 检查数据库现有冲突
	var existingUsers []configs.User
	if err := tx.Where("username IN ?", allUsernames).Find(&existingUsers).Error; err != nil {
		tx.Rollback()
		JsonResponse(c, http.StatusInternalServerError, "数据库查询失败", nil)
		return
	}
	existingMap := make(map[string]bool)
	for _, u := range existingUsers {
		existingMap[u.Username] = true
	}
	// 准备有效用户列表
	validUsers := make([]configs.User, 0)
	conflicts := make([]string, 0)
	for _, user := range users {
		if existingMap[user.Username] {
			conflicts = append(conflicts, user.Username)
			continue
		}
		if user.Password == "" {
		    user.Password = "123456"
		}
		// 加密密码
		hashedPassword, err := configs.HashPassword(user.Password)
		if err != nil {
			tx.Rollback()
			JsonResponse(c, http.StatusInternalServerError, 
				fmt.Sprintf("用户[%s]密码加密失败", user.Username), nil)
			return
		}
		user.Password = hashedPassword
		validUsers = append(validUsers, user)
	}
	if len(conflicts) > 0 {
		tx.Rollback()
		JsonResponse(c, http.StatusConflict, "部分用户名已存在", gin.H{"conflict_usernames": conflicts,})
		return
	}
	if len(validUsers) == 0 {
		tx.Rollback()
		JsonResponse(c, http.StatusBadRequest, "没有有效用户可导入", nil)
		return
	}
	// 批量创建用户
	if err := tx.Create(&validUsers).Error; err != nil {
		tx.Rollback()
		JsonResponse(c, http.StatusInternalServerError, "用户保存失败", nil)
		return
	}
	// 提交事务
	if err := tx.Commit().Error; err != nil {
		tx.Rollback()
		JsonResponse(c, http.StatusInternalServerError, "事务提交失败", nil)
		return
	}
    go func() {
        configs.CreateMessage(nil, currentUser.ID, "批量导入用户", fmt.Sprintf("批量导入用户：%d个，时间：%s", len(validUsers), time.Now().Format("2006-01-02 15:04")))
    }()
	JsonResponse(c, http.StatusOK, "批量导入成功", gin.H{
		"success_count":    len(validUsers),
		"total_requested": len(users),
	})
}

// 注册或添加用户
func Register(c *gin.Context) {
    var user configs.User
    if err := c.ShouldBindJSON(&user); err != nil {
        JsonResponse(c, http.StatusBadRequest, err.Error(), nil)
        return
    }
    // 检查用户名是否存在
    if err := configs.DB.Where("username = ?", user.Username).First(&configs.User{}).Error; err == nil {
        JsonResponse(c, http.StatusConflict, "用户名已存在", nil)
        return
    }
    if err := configs.DB.Where("email = ?", user.Email).First(&configs.User{}).Error; err == nil {
        JsonResponse(c, http.StatusConflict, "邮箱已被注册", nil)
        return
    }
    if err := configs.DB.Where("phone = ?", user.Phone).First(&configs.User{}).Error; err == nil {
        JsonResponse(c, http.StatusConflict, "手机号已被注册", nil)
        return
    }
    // 加密密码
    hashedPassword, err := configs.HashPassword(user.Password)
    if err != nil {
        JsonResponse(c, http.StatusInternalServerError, "密码加密失败", nil)
        return
    }
    user.Password = hashedPassword
    // 使用事务处理用户创建和欢迎消息
    err = configs.DB.Transaction(func(tx *gorm.DB) error {
        // 创建用户
        if err := tx.Create(&user).Error; err != nil {
            return err
        }
        // 创建欢迎消息
        return configs.CreateMessage(tx, user.ID, "欢迎注册", fmt.Sprintf("您好%s，欢迎加入我们！", user.Username))
    })
    if err != nil {
        JsonResponse(c, http.StatusInternalServerError, err.Error(), nil)
        return
    }
    JsonResponse(c, http.StatusOK, "注册成功", nil)
}

// 修改用户
func UpdateUser(c *gin.Context) {
    currentUser := GetCurrentUser(c)
    if currentUser == nil {
        JsonResponse(c, http.StatusUnauthorized, "请先登录", nil)
        return
    }
    var user configs.User
    if err := c.ShouldBindJSON(&user); err != nil {
        JsonResponse(c, http.StatusBadRequest, err.Error(), nil)
        return
    }
    // 检查用户是否存在
    var existingUser configs.User
    if err := configs.DB.Where("id = ?", user.ID).First(&existingUser).Error; err != nil {
        JsonResponse(c, http.StatusNotFound, "用户不存在", nil)
        return
    }
    // 检查用户名是否被其他用户占用（排除自己）
    if user.Username != existingUser.Username {
        if err := configs.DB.Where("username = ? AND id != ?", user.Username, user.ID).First(&configs.User{}).Error; err == nil {
            JsonResponse(c, http.StatusConflict, "用户名已被占用", nil)
            return
        }
    }
    if user.Email != existingUser.Email {
        if err := configs.DB.Where("email = ? AND id != ?", user.Email, user.ID).First(&configs.User{}).Error; err == nil {
            JsonResponse(c, http.StatusConflict, "邮箱已被占用", nil)
            return
        }
    }
    if user.Phone != existingUser.Phone {
        if err := configs.DB.Where("phone = ? AND id != ?", user.Phone, user.ID).First(&configs.User{}).Error; err == nil {
            JsonResponse(c, http.StatusConflict, "手机号已被占用", nil)
            return
        }
    }
    // 仅当密码非空时更新密码
    if user.Password != "" {
        hashedPassword, err := configs.HashPassword(user.Password)
        if err != nil {
            JsonResponse(c, http.StatusInternalServerError, "密码加密失败", nil)
            return
        }
        user.Password = hashedPassword
    } else {
        // 保留原密码
        user.Password = existingUser.Password
    }
    if err := configs.DB.Select("Name", "Phone", "Password", "Email", "Role", "Points", "OpenID").Updates(&user).Error; err != nil {
        JsonResponse(c, http.StatusInternalServerError, err.Error(), nil)
        return
    }
    go func() {
        err := configs.CreateMessage(nil, currentUser.ID, "修改用户信息", fmt.Sprintf("修改用户%s的信息，时间：%s", user.Username, time.Now().Format("2006-01-02 15:04")))
        fmt.Println(err)
    }()
    userCacheKey := fmt.Sprintf("user:%d", user.ID) //删除缓存
    configs.CRdb.Delete(userCacheKey)
    JsonResponse(c, http.StatusOK, "修改成功", nil)
}

// 最大登录尝试次数和过期时间设置
const (
	maxLoginAttempts = 5                // 最大登录尝试次数
	blockDuration    = 30               // 被封锁时长，单位为分钟
	attemptDuration  = 1 * time.Hour    // 登录尝试次数的缓存过期时间，单位为小时
)
// 登录 API
func Login(c *gin.Context) {
	var loginData struct {
		Username string `json:"username"`
		Password string `json:"password"`
	}
	if err := c.ShouldBindJSON(&loginData); err != nil {
		JsonResponse(c, http.StatusBadRequest, err.Error(), nil)
		return
	}
	// 获取客户端IP地址
	clientIP := c.ClientIP()
    // 生成基于 IP + 用户名的唯一键
    key := fmt.Sprintf("%s_%s", clientIP, loginData.Username)
    lockKey := fmt.Sprintf("lock_%s_%s", clientIP, loginData.Username)
    // 从缓存中获取该 IP+用户名的登录尝试次数和封锁时间
    attempts, found := configs.CRdb.Get(key)
    lockTime, _ := configs.CRdb.Get(lockKey)
    // 如果该 IP+用户名已经被封锁
    if found && lockTime != nil {
        lockTimestamp := lockTime.(time.Time)
        if time.Now().Before(lockTimestamp) {
            remainingTime := lockTimestamp.Sub(time.Now())
            JsonResponse(c, http.StatusTooManyRequests,fmt.Sprintf("登录尝试次数过多，请在 %d 分钟后再试", int(remainingTime.Minutes())), nil)
            return
        }
        // 封锁时间已过，清除封锁状态
        configs.CRdb.Delete(lockKey)
    }
    // 如果登录尝试次数超过限制，进行封锁
    if attempts != nil && attempts.(int) >= maxLoginAttempts {
        configs.CRdb.Set(lockKey, time.Now().Add(time.Minute*blockDuration), cache.DefaultExpiration)
        JsonResponse(c, http.StatusTooManyRequests, fmt.Sprintf("登录尝试次数过多，请在 %d 分钟后再试", blockDuration), nil)
        return
    }
    // 用户名和密码的验证
    var user configs.User
    if err := configs.DB.Where("username = ?", loginData.Username).First(&user).Error; 
        err != nil || !configs.CheckPasswordHash(loginData.Password, user.Password) {
        // 验证失败，增加 IP+用户名的尝试次数
        if attempts == nil {
            attempts = 0
        }
        attemptsCount := attempts.(int) + 1
        configs.CRdb.SetDefault(key, attemptsCount)
        // 超过最大尝试次数则封锁
        if attemptsCount >= maxLoginAttempts {
            configs.CRdb.Set(lockKey, time.Now().Add(time.Minute*blockDuration), cache.DefaultExpiration)
            JsonResponse(c, http.StatusTooManyRequests, 
                fmt.Sprintf("登录尝试次数过多，请在 %d 分钟后再试", blockDuration), nil)
            return
        }
        // 返回动态剩余次数
        remainingAttempts := maxLoginAttempts - attemptsCount
        JsonResponse(c, http.StatusTooManyRequests, fmt.Sprintf("密码错误，还剩%d次机会", remainingAttempts), nil)
        return
    }
    // 登录成功，清除该 IP+用户名的尝试次数
    configs.CRdb.Delete(key)
	// 生成Token
	token, err := GenerateToken(&user)
	if err != nil {
		JsonResponse(c, http.StatusInternalServerError, err.Error(), nil)
		return
	}
    // 登录成功时发送通知
    go func() {
        configs.CreateMessage(nil, user.ID, "登录安全提醒", fmt.Sprintf("检测到从IP %s 的登录操作，时间：%s", clientIP, time.Now().Format("2006-01-02 15:04")))
    }()
	JsonResponse(c, http.StatusOK, "登录成功", gin.H{
		"token": token,
		"user": gin.H{
			"id":       user.ID,
			"username": user.Username,
			"role":     user.Role,
			"openid":   user.OpenID,
			"points":   user.Points,
			"last_check_in": user.LastCheckIn,
		},
	})
}

// 删除用户请求结构体
type DeleteUserRequest struct {
    IDs []uint `json:"ids" binding:"required,min=1"` // 必须包含至少一个ID
}

// 删除用户
func DeleteUser(c *gin.Context) {
    var req DeleteUserRequest
    if err := c.ShouldBindJSON(&req); err != nil {
        JsonResponse(c, http.StatusBadRequest, "请求格式错误", nil)
        return
    }
    currentUser := GetCurrentUser(c)
    if currentUser == nil {
        JsonResponse(c, http.StatusUnauthorized, "请先登录", nil)
        return
    }
    // 事务处理
    err := configs.DB.Transaction(func(tx *gorm.DB) error {
        // 查询目标用户（防止删除不存在的用户）
        var targets []configs.User
        if err := tx.Where("id IN ?", req.IDs).Find(&targets).Error; err != nil {
            return err
        }
        // 校验实际找到的用户数
        if len(targets) == 0 {
            return errors.New("用户不存在")
        }
        // 安全保护校验
        for _, user := range targets {
            if user.ID == currentUser.ID {
                return errors.New("不能删除自己")
            }
            userCacheKey := fmt.Sprintf("user:%d", user.ID) //删除缓存
            configs.CRdb.Delete(userCacheKey)
        }
        // 执行删除
        if err := tx.Where("id IN ?", req.IDs).Delete(&configs.User{}).Error; err != nil {
            return err
        }
        return nil
    })
    // 错误处理
    if err != nil {
        switch err.Error() {
        case "用户不存在":
            JsonResponse(c, http.StatusNotFound, err.Error(), nil)
        case "不能删除自己":
            JsonResponse(c, http.StatusForbidden, err.Error(), nil)
        default:
            JsonResponse(c, http.StatusInternalServerError, "删除操作失败", nil)
        }
        return
    }
    go func() {
        // 将 ID 列表转换为可读字符串（例如 "1,5,23"）
        idStrings := make([]string, len(req.IDs))
        for i, id := range req.IDs {
            idStrings[i] = strconv.FormatUint(uint64(id), 10)
        }
        deletedIDs := strings.Join(idStrings, ",")
        configs.CreateMessage(nil, currentUser.ID, "批量删除用户", fmt.Sprintf("共删除：%d个，分别为%s，时间：%s", len(req.IDs), deletedIDs,  time.Now().Format("2006-01-02 15:04")))
    }()
    JsonResponse(c, http.StatusOK, "用户删除成功", nil)
}

// 用户更新请求结构体
type UpdateRequest struct {
    OldPassword string `json:"old_password,omitempty"`
    NewPassword string `json:"new_password,omitempty" binding:"omitempty,min=6,max=20"`
    Name        string `json:"name,omitempty" binding:"omitempty,max=100"`
    Phone       string `json:"phone,omitempty" binding:"omitempty,len=11,numeric"`
    Email       string `json:"email,omitempty" binding:"omitempty,email"`
}

// 前端用户更新密码和姓名、手机、邮箱
func UpdateUserProfile(c *gin.Context) {
    var req UpdateRequest
    if err := c.ShouldBindJSON(&req); err != nil {
        JsonResponse(c, http.StatusBadRequest, "请求数据格式错误", nil)
        return
    }
    currentUser := GetCurrentUser(c)
    if currentUser == nil {
        JsonResponse(c, http.StatusUnauthorized, "请先登录", nil)
        return
    }
    // 密码修改强制验证规则
    if req.NewPassword != "" && req.OldPassword == "" {
        JsonResponse(c, http.StatusBadRequest, "修改密码需要提供旧密码", nil)
        return
    }
    var user configs.User
    if err := configs.DB.First(&user, currentUser.ID).Error; err != nil {
        JsonResponse(c, http.StatusNotFound, "用户不存在", nil)
        return
    }
    err := configs.DB.Transaction(func(tx *gorm.DB) error {
        updateData := make(map[string]interface{})
        // 处理密码修改
        if req.NewPassword != "" {
            // 验证旧密码
            if !configs.CheckPasswordHash(req.OldPassword, user.Password) {
                return errors.New("旧密码验证失败")
            }
            // 新密码加密
            if hashed, err := configs.HashPassword(req.NewPassword); err == nil {
                updateData["password"] = hashed
            } else {
                return err
            }
        }
        // 基本信息模块
        if req.Name != "" && req.Name != user.Name {
            updateData["name"] = req.Name
        }
        if req.Phone != "" {
            if !configs.ValidatePhone(req.Phone) {
                return errors.New("手机号格式错误")
            }
            updateData["phone"] = req.Phone
        }
        if req.Email != "" {
            if !configs.ValidateEmail(req.Email) {
                return errors.New("邮箱格式错误")
            }
            updateData["email"] = req.Email
        }
        // 执行更新
        if len(updateData) == 0 {
            return errors.New("未检测到有效修改")
        }
        // 先执行用户更新
        if err := tx.Model(&user).Updates(updateData).Error; err != nil {
            return err
        }
        // 密码修改成功后添加消息
        if req.NewPassword != "" {
            return configs.CreateMessage(tx, user.ID, "密码修改通知", "您的账户密码已成功修改，若非本人操作请立即联系管理员。")
        }
        return nil
    })
    // 错误处理增强
    if err != nil {
        switch err.Error() {
        case "旧密码验证失败":
            JsonResponse(c, http.StatusForbidden, "原密码错误", nil)
        case "手机号格式错误":
            JsonResponse(c, http.StatusBadRequest, "请输入11位有效手机号", nil)
        case "邮箱格式错误":
            JsonResponse(c, http.StatusBadRequest, "邮箱格式不正确", nil)
        case "未检测到有效修改":
            JsonResponse(c, http.StatusBadRequest, "未修改任何信息", nil)
        default:
            JsonResponse(c, http.StatusInternalServerError, "系统错误，请稍后再试", nil)
        }
        return
    }
    userCacheKey := fmt.Sprintf("user:%d", currentUser.ID)  //删除缓存
    configs.CRdb.Delete(userCacheKey)
    JsonResponse(c, http.StatusOK, "更新成功", nil)
}

//校验登录状态
func VerifyToken(c *gin.Context) {
    user := GetCurrentUser(c)
    if user == nil {
		JsonResponse(c, http.StatusUnauthorized, "请重新登录", nil)
		return
	}
    JsonResponse(c, http.StatusOK, "登录状态正常", user)
}